﻿/*SharpConsole Utils module
 * Contains helpful functions
 * 
 * Original Author: Scott Ketelaar
 * Original Creation: 3/16/2011
 * 
 * Most Recent Update: 3/16/2011 by Scott Ketelaar
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using CSScriptLibrary;

namespace SharpConsole
{
    /// <summary>
    /// Class contains helpful methods for stipping arguments, ect
    /// </summary>
    internal class Utils
    {
    	private static Utils _Utils = new Utils();
        /// <summary>
        /// Processes a string and returns the arguments in an array. Also provides the command without arguments.
        /// </summary>
        /// <param name="Command">The string to process</param>
        /// <param name="StrippedCommand">The returned command without args</param>
        /// <param name="NormalizeSwitches">Change every switch ("-", "/", ect) to "-"</param>
        /// <param name="WarnIfNonswitchedArg">Controls if we print a warning about nonswitched arguments. Also controls notification of correcting a missing switch.</param>
        /// <param name="CorrectMissingSwitches">Automatically adds the "-" to arguments, if necessary. Prints a message if WarnIfNonswitchedArg is true</param>
        /// <returns>A System.Array of strings containing arguments.</returns>
        internal static string[] GetArgs(string Command, out string StrippedCommand, 
            bool NormalizeSwitches, bool WarnIfNonswitchedArg, bool CorrectMissingSwitches)
        {
            try
            {
                List<string> Args = new List<string>();
                for (int Start = 0; Start < Command.Length; Start++)
                {
                    string TmpCmd = "";
                    if (Command[Start] == '"')
                    {

                        for (int End = Start + 1; End < Command.Length - 1; End++) //Modified to exclude the quotes
                        {
                            if (Command[End] != '"')
                            {
                                TmpCmd += Command[End];
                                Start = End;
                            }
                            else
                            {
                                Start = End + 1;
                                break;
                            }
                        }
                    }
                    else if (Command[Start] != ' ')
                    {
                        for (int End = Start; End < Command.Length; End++)
                        {
                            if (Command[End] != ' ')
                            {
                                TmpCmd += Command[End];
                                Start = End;
                            }
                            else
                            {
                                Start = End;
                                break;
                            }
                        }
                    }
                    if (NormalizeSwitches && (TmpCmd.StartsWith("-") || TmpCmd.StartsWith("/")))
                    {
                        TmpCmd = "-" + TmpCmd.Substring(1); //Strip out switch and replace it with normalized
                    }
                    if (WarnIfNonswitchedArg)
                        if (!(TmpCmd.StartsWith("-") || TmpCmd.StartsWith("/")) && Args.Count != 0) //We dont want to correct the command itself
                        {
                            if (WarnIfNonswitchedArg)
                                Console.WriteLine("Warning: Unswitched argument detected: {0}. This argument will " +
                                    (CorrectMissingSwitches ? "" : "not ") + "be corrected automatically.", TmpCmd);

                            if (CorrectMissingSwitches)
                                TmpCmd = "-" + TmpCmd;
                        }
                    Args.Add(TmpCmd);
                }
                StrippedCommand = Args[0];
                Args.RemoveAt(0);
                return Args.ToArray<string>();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while processing arguments: {0}", ex.ToString());
                StrippedCommand = Command;
                return new string[] { "" };
            }
            finally
            {
                Console.WriteLine();
            }
        }

        /// <summary>
        /// Concatenates an array of strings, with spaces in between.
        /// </summary>
        /// <param name="elements">The System.Array to concatenate</param>
        /// <returns>A System.String conatinig the conactenated elements</returns>
        internal static string ConcatWithSpaces(string[] elements)
        {
            string Ret = "";
            foreach (string e in elements)
                Ret += e + " ";

            return Ret.Trim();
        }

        internal static List<string> MatchFile(string CharsEntered)
        {
            return RegExMatchArray(GetAllItemsInCD().ToArray<string>(), "\\A" + CharsEntered + ".*");
        }
        internal static List<string> GetAllItemsInCD() {
        	List<string> LS = new List<string>();
        	LS.AddRange(System.IO.Directory.GetDirectories(Environment.CurrentDirectory).ToList());
        	LS.AddRange(System.IO.Directory.GetFiles(Environment.CurrentDirectory).ToList());
        	LS.Sort();
        	return LS;
        }
        internal static List<string> RegExMatchArray(string[] sArray, string pattern) {
        	List<string> MC = new List<string>();
        	foreach(string s in sArray) {
                if (System.Text.RegularExpressions.Regex.IsMatch(GetRelativePath(s),pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase))
        		    MC.Add(System.Text.RegularExpressions.Regex.Match(GetRelativePath(s),pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase).Value);
        	}
            return MC;
        }
        internal static string GetRelativePath(string path)
        {
            for (int i = path.Length - 2; i >= 0; i--)
            {
                if (path.Substring(i, 1) == System.IO.Path.DirectorySeparatorChar.ToString())
                    return path.Substring(i + 1);
            }
            return path;
        }
        internal static string MeshStrings(string String1, string String2)
        {
            //TODO: Impliment actual algorithm
            //string ModS1 = String1.ToUpper();
            //string ModS2 = String2.ToUpper();
            //for (int P = 0; P < ModS1.Length; P++)
            //{
            //    if (ModS1[P] != ModS2[P])
            //    {

            //    }
            //}
            return String2;
        }
        internal static void ExcecuteCSfile(string filename, string Method) {
        	//TODO: Add functionality
        	if (_Utils == null) _Utils = new Utils();
        	if (Method.Length == 0) Method = "Main";
        		_Utils.ExecuteAndUnloadScript(filename,Method);
        }
        private void ExecuteAndUnloadScript(string script,string Method)
    {
        using (CSScriptLibrary.AsmHelper helper = new CSScriptLibrary.AsmHelper(CSScriptLibrary.CSScript.Compile(Path.GetFullPath(script), null, true), null, true))
        {
            helper.Invoke("*."+ Method);
        }
    }
    }
}
